#include <Windows.h>
//#include <windowsx.h>
#include <stdio.h>
#include <tchar.h>
#include <malloc.h>
#include <TlHelp32.h>
#include <strsafe.h>

#ifdef UNICODE
	#define InjectLib InjectLibW
	#define EjectLib EjectLibW
#else
	#define InjectLib InjectLibA
	#define EjectLib EjectLibA
#endif

BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile){
	BOOL bOK = FALSE;
	HANDLE hProcess = NULL, hThread = NULL;
	PWSTR pszLibFileRemote = NULL;

	__try{
		hProcess = OpenProcess(
			PROCESS_QUERY_INFORMATION|
			PROCESS_CREATE_THREAD|
			PROCESS_VM_OPERATION|
			PROCESS_VM_WRITE,
			FALSE, dwProcessId);
		if(hProcess == NULL) __leave;

		int cch = 1 + lstrlenW(pszLibFile);
		int cb = cch * sizeof(wchar_t);

		pszLibFileRemote = (PWSTR)
			VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
		if(pszLibFileRemote == NULL) __leave;

		if(!WriteProcessMemory(hProcess, pszLibFileRemote,
			(PVOID)pszLibFile, cb, NULL)) __leave;

		PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
			GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
		if(pfnThreadRtn == NULL) __leave;

		hThread = CreateRemoteThread(hProcess, NULL, 0,
			pfnThreadRtn, pszLibFileRemote, 0, NULL);
		if(hThread == NULL) __leave;

		WaitForSingleObject(hThread, INFINITE);

		bOK = TRUE;
	}
	__finally{
		if(pszLibFileRemote != NULL)
			VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

		if(hThread != NULL)
			CloseHandle(hThread);

		if(hProcess != NULL)
			CloseHandle(hProcess);
	}

	return(bOK);
}

BOOL WINAPI InjectLibA(DWORD dwProcessId, PCSTR pszLibFile){
	SIZE_T cchSize = lstrlenA(pszLibFile) + 1;
	PWSTR pszLibFileW = (PWSTR)_alloca(cchSize * sizeof(wchar_t));

	StringCchPrintfW(pszLibFileW, cchSize, L"%S", pszLibFile);

	return(InjectLibW(dwProcessId, pszLibFileW));
}

BOOL WINAPI EjectLibW(DWORD dwProcessId, PCWSTR pszLibFile){
	BOOL bOK = FALSE;
	HANDLE hthSnapshot = NULL;
	HANDLE hProcess = NULL, hThread = NULL;

	__try{
		hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
		if(hthSnapshot == INVALID_HANDLE_VALUE) __leave;

	}
	__finally{
		
		if(hthSnapshot != NULL)
			CloseHandle(hthSnapshot);
	}
}